package com.nfcprogram;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.nfc.NfcAdapter;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.nfc.tech.NfcF;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.lamerman.FileDialog;
import com.lamerman.SelectionMode;
import com.nfcprogram.blu.BluetoothService;
import com.nfcprogram.device.AppMessages;
import com.nfcprogram.device.DeviceManager;
import com.nfcprogram.device.enums.Network;
import com.nfcprogram.exception.NfcProgramException;
import com.nfcprogram.handover.HandoverManager;
import com.nfcprogram.util.Util;
import com.nfcprogram.wifi.WiFiConstants;

public class PresentationAppActivity extends Activity {
	
	//Constants
	public static final String NEXT = "^NEXT^";
	public static final String PREVIOUS = "^PREVIOUS^";
	public static final String GOTO = "^GOTO^";
	public static final String START = "^START^";
	public static final String FINISH = "^FINISH^";
	//MenuItens
	private static final int CHOOSE_FILE = 0;
	private static final int STARTOVER = 1;
	private static final int ABOUT = 2;
	
	

	// Key names received from the BluetoothCommandService Handler
	public static final String DEVICE_NAME = "device_name";
	public static final String TOAST = "toast";
	protected static final String PRESENTATION_ACTIVITY = "PresentationAppActivity";
	private static final int REQUEST_LOAD = 1;

	private EditText editText;
	private ImageButton nextButton, previousButton;
	private Button  goButton;
	private static ProgressDialog dialog;
	
	//Device Manager
	private DeviceManager deviceManager;
	
	
	
	//NFC Stuff's
	private String[][] techListsArray;
	private IntentFilter[] intentFiltersArray;
	private PendingIntent pendingIntent;
	private NfcAdapter nfcAdapter;
	private ImageView connectionImageView;
	private TextView slideNumTextView, fileNameTextView;
	private String shortFileName;
	
	

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.mylayout);
		
		deviceManager = new DeviceManager(mHandler, this);
		
		
		editText = (EditText)findViewById(R.id.editText1); editText.setText("");  editText.setWidth(150);
		goButton = (Button)findViewById(R.id.goButton); goButton.setWidth(150); goButton.setText("Go!");
		nextButton = (ImageButton)findViewById(R.id.nextImageButton);
		previousButton = (ImageButton)findViewById(R.id.previousImageButton);
		connectionImageView = (ImageView)findViewById(R.id.connectionImageView);
		slideNumTextView = (TextView)findViewById(R.id.slideNumTextView); slideNumTextView.setText("");
		fileNameTextView = (TextView)findViewById(R.id.fileNameTextView); 
		
		connectionImageView.setImageResource(R.drawable.nonetwork);
		//connectionImageView.setVisibility(ImageView.INVISIBLE);
		nextButton.setImageResource(R.drawable.rightarrow);
		previousButton.setImageResource(R.drawable.leftarrow);
		
		
		nextButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				enviarDados(NEXT);
			}
		});
		
		previousButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				enviarDados(PREVIOUS);
			}
		});
		
		goButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String texto = editText.getText().toString();
				if(texto.contains("w")){
					Log.e(PRESENTATION_ACTIVITY, "!! Enviando Handover to Wifi message");
					try {
						HandoverManager.getInstance().makeHandover(Network.WiFi, false);
					} catch (NfcProgramException e) {
						e.printStackTrace();
					}
					return;
				}
				if(texto.contains("b")){
					Log.e(PRESENTATION_ACTIVITY, "!! Enviando Handover to Bluetooth message");
					try {
						HandoverManager.getInstance().makeHandover(Network.Bluetooth, false);
					} catch (NfcProgramException e) {
						e.printStackTrace();
					}
					return;
				}
				
				try {
					int num = Integer.parseInt(texto.trim());
					enviarDados(GOTO + num +"^");
				} catch (NumberFormatException e) {
					showToast(texto.trim() + " não é um número válido");
				}
			}
		});

		initNFC();
	}
	
	@Override
	public boolean onCreateOptionsMenu(android.view.Menu menu) {
		super.onCreateOptionsMenu(menu);
		
		menu.add(0, CHOOSE_FILE, 0,"Choose file");
		menu.add(0, STARTOVER, 0,"Start over");
		menu.add(0, ABOUT, 0,"About");
		return true;
	}
	
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		super.onMenuItemSelected(featureId, item);
		switch (item.getItemId()) {
			case CHOOSE_FILE:
				//fazer
				Intent intent = new Intent(this.getBaseContext(),FileDialog.class);
				intent.putExtra(FileDialog.START_PATH, "/sdcard");
				intent.putExtra(FileDialog.SELECTION_MODE, SelectionMode.MODE_OPEN);
				this.startActivityForResult(intent, REQUEST_LOAD);
				return true;
			case STARTOVER:
				String txt = (String)fileNameTextView.getText();
				if(!txt.equalsIgnoreCase("Not chosen"))
					enviarDados(START);
				return true;
			case ABOUT:
				Log.e(PRESENTATION_ACTIVITY, "!! Enviando Handover to Bluetooth message");
				try {
					HandoverManager.getInstance().makeHandover(Network.Bluetooth, false);
				} catch (NfcProgramException e) {
					e.printStackTrace();
				}
				return true;
			default:
				return false;
		}
	}
	@Override
	 public synchronized void onActivityResult(final int requestCode,
         int resultCode, final Intent data) {
         if (resultCode == Activity.RESULT_OK) {
                 String filePath = data.getStringExtra(FileDialog.RESULT_PATH);
                 StringTokenizer tk = new StringTokenizer(filePath,"//");
                 String nome = "";
                 while(tk.hasMoreTokens()){
                	 nome = tk.nextToken();
                 }
                 shortFileName = nome;
                 //fileNameTextView.setText(nome);
                 Log.d(PRESENTATION_ACTIVITY, "filePath= "+ filePath);
                 criarBarraDeProgresso(nome);
                 sendFile(filePath);
                 
         } else if (resultCode == Activity.RESULT_CANCELED) {
        	 Log.d(PRESENTATION_ACTIVITY, " File chooser canceled");
         }
     }

	
	
	
	 @Override
    public void onNewIntent(Intent intent) {    	
    	try {
			if(deviceManager.start(intent)) {
				showToast("Card read: "+ "Wifi=  "+ deviceManager.getNfcManager().getWifi()+'\n'+"Bluetooth= "+deviceManager.getNfcManager().getBlu());
			}else{
				showToast("Erro: Leitura de WiFi e/ou Bluetooth inválida: "+ "Wifi= "+deviceManager.getNfcManager().getWifi()+'\n'+"Bluetooth= "+deviceManager.getNfcManager().getWifi());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }


	@Override
	public void onResume() {
		super.onResume();
		nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
	}

	@Override
	public void onPause() {
		super.onPause();
		nfcAdapter.disableForegroundDispatch(this);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		deviceManager.stop();
	}

	@Override
	protected void onStart() {
		super.onStart();
	}

	
	
	@Override
	public void onBackPressed(){
		enviarDados(FINISH);
		deviceManager.stop();
		super.onBackPressed();
	}
	
	// The Handler that gets information back from the BluetoothChatService
	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case AppMessages.MESSAGE_STATE_CHANGE:
				switch (msg.arg1) {
				case BluetoothService.STATE_CONNECTED:
					showToast("Conectado a "	+ deviceManager.getBluetoothService().getmConnectedDeviceName());
					break;
				case BluetoothService.STATE_CONNECTING:
					/*Toast.makeText(getApplicationContext(),
							"Conectando...", Toast.LENGTH_LONG)
							.show();*/
					break;
				case BluetoothService.STATE_LISTEN:
				case BluetoothService.STATE_NONE:
					/*Toast.makeText(getApplicationContext(),
							"Não conectado...", Toast.LENGTH_LONG)
							.show();*/
					break;
				}
				break;
			case AppMessages.MESSAGE_DEVICE_NAME:
				String mConnectedDeviceName = msg.getData().getString(
						DEVICE_NAME);
				if(mConnectedDeviceName == null)
					mConnectedDeviceName = msg.getData().getString(WiFiConstants.CONNECTED_HOST_NAME);
				showToast("Connected to " + mConnectedDeviceName);
				break;
			case AppMessages.MESSAGE_READ:
				 byte[] buffer  = (byte[]) msg.obj;
				 if(buffer == null) break;
				 String out = new String(buffer);
				 try {
					 StringTokenizer tokenizer = new StringTokenizer(out,"^");
					 tokenizer.nextToken();
					 String numero = tokenizer.nextToken();
					 String nomeArquivo = tokenizer.nextToken();
					 int slideNum = Integer.parseInt(numero);
					 slideNumTextView.setText("Current Slide:  " + slideNum);
					 fileNameTextView.setText(nomeArquivo);
				} catch (NoSuchElementException e) {
					Log.e(PRESENTATION_ACTIVITY, "!! Erro ao receber mensagem: tokenizer");
				} catch (NumberFormatException e) {
					Log.e(PRESENTATION_ACTIVITY, "!! Erro ao receber mensagem: parseInt");
				}
				 
				break;
			case AppMessages.MESSAGE_PROTOCOL:
				if(msg.arg1 == Network.Bluetooth.getValue()){
					connectionImageView.setImageResource(R.drawable.bluetooth);
					connectionImageView.setVisibility(ImageView.VISIBLE);
				} else {
					connectionImageView.setImageResource(R.drawable.wifi);
					connectionImageView.setVisibility(ImageView.VISIBLE);
				}
				break;
			}
		}
	};
	private EnviarArquivoThread enviarArquivoThread;

	public void showToast(String string) {
		Toast makeText = Toast.makeText(this, string, Toast.LENGTH_LONG);
		makeText.setGravity(Gravity.BOTTOM|Gravity.CENTER, 0, 0);
		makeText.show();
	}

	public void enviarDados(String output){
		try {
			deviceManager.writeData(output.getBytes());
		} catch (NfcProgramException e) {
			e.printStackTrace();
			Log.e(PRESENTATION_ACTIVITY,e.getMessage(), e);
		}
	}



	private void initNFC() {
		nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndef.addDataType("*/*");   
        }
        catch (MalformedMimeTypeException e) {
            throw new RuntimeException("Deu erro!", e);
        }
        
        intentFiltersArray = new IntentFilter[] { ndef };
        techListsArray = new String[][] { new String[] { NfcF.class.getName(), Ndef.class.getName(), NdefFormatable.class.getName() } };
        
        try {
        	//nfcManager.readCardData(getIntent());
        	this.onNewIntent(getIntent());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	   
	 private void criarBarraDeProgresso(String nomeDoArquivo) {
		 dialog = new ProgressDialog(this);
		 dialog.setTitle("Sending " + nomeDoArquivo);
		 dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		 dialog.setMax(100);
		 dialog.setButton(DialogInterface.BUTTON_NEGATIVE,
		        "Cancel", new DialogInterface.OnClickListener() {
		     public void onClick(DialogInterface dialog, int whichButton) {
		    	 if(enviarArquivoThread != null){
		    		 enviarArquivoThread.interrupt();
		    	 }
		     }
		 });
		 dialog.show();
	}
	 
	 private void sendFile(String fileName) {
		enviarArquivoThread = new EnviarArquivoThread(fileName);
		enviarArquivoThread.start();
	}
	 
	 
	 private class EnviarArquivoThread extends Thread{
		private final String fileFullPath;
		
		private boolean continuar;

		public EnviarArquivoThread(String fileName) {
			this.fileFullPath = fileName;
			continuar = true;
		}

		@Override
         public void run() {
     	   enviarArquivo();
         }
        
        private void enviarArquivo() {
    		try {
				String fileType = fileFullPath.substring(fileFullPath.indexOf(".") +1, fileFullPath.length());
    			File file = new File(fileFullPath);
    			long fileLength = file.length();
    			
    			FileInputStream fis = new FileInputStream(file);
    		    int bufferSize = 8*1000;
    		    byte [] buffer = new byte[bufferSize];
    		   
    		    Integer bytesRead = 0;  
    		    boolean firstTime = true;
    		    String header = "#F";
    		    String nomeDoArquivo = PresentationAppActivity.this.shortFileName.substring(0, PresentationAppActivity.this.shortFileName.indexOf("."));
				String saida = header + "N" +(nomeDoArquivo.length() == 2? nomeDoArquivo.length(): "0" + nomeDoArquivo.length() ) +nomeDoArquivo;;
    		    DeviceManager.getInstance().writeData(saida.getBytes());
    		    Thread.sleep(300);
    		    saida = header + "T" + fileType;
    		    DeviceManager.getInstance().writeData(saida.getBytes());
    		    
    		    int count  = 0;
    		   // int  testelength = 0, contadorBytes = 0;
    		    while (((bytesRead = fis.read(buffer)) > 0) && continuar) {
    		    	header += (bytesRead == bufferSize ? (firstTime ? "B" : "R") : "E");
    		    	int length = new String(++count + "").length();
    				header += (length == 3? "": (length == 2? "0": "00" ) ) + count;
    		    	
    		    	String bytesReadString = bytesRead + "";
    		    	header += (bytesReadString.length() == 5 ?"":(bytesReadString.length() == 4 ? "0":(bytesReadString.length() == 3 ? "00":(bytesReadString.length() == 2 ?"000":"0000")))) + bytesReadString;
    		    	
    		    	byte[] data = Arrays.copyOf(buffer, bytesRead);
    				byte[] headerBytes = header.getBytes();
    				byte[] output = Util.concat(headerBytes , data);
    				//contadorBytes += headerBytes.length + output.length; 
    		    	//Log.d(HYBRID_ACTIVITY, "! header= "+header +" output.length= "+ output.length);
    		    	Log.d(PRESENTATION_ACTIVITY, "! enviando pacote "+count +" com length "+ output.length);
    		    	Thread.sleep(300);
    		    	DeviceManager.getInstance().writeData(output);
    		        firstTime = false;
    		        header = "#F";

    		        
    		        float i = fileLength / bufferSize;
    		        float j =  count /i;
    		        int progresso = (int)(j*100);
    		        
					dialog.setProgress(progresso);
    		    }
    				Log.d(PRESENTATION_ACTIVITY, "! numero de pacotes enviados= "+ count);
    				dialog.dismiss();//handler.sendEmptyMessage(0);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
        
        	@Override
        	public void interrupt() {
        		super.interrupt();
        		continuar = false;
        	}
	 }
	

	
	
	

}
